package auctionhausen

import grails.test.mixin.*

/**
 * See the API for {@link grails.test.mixin.domain.DomainClassUnitTestMixin} for 
 * usage instructions.
 */
@TestFor(Customer)
class CustomerUnitTests {
	
	//Email constants
	static final def VALID_EMAILS = ['test@test.com']
	static final def INVALID_EMAILS = [null, '', 'test', 'test@', 'test@test']
	
	//email regex pattern for validating constants
	static final def emailPattern = 
		~/^([0-9a-zA-Z]([-\.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$/
		
	//closure used to verify email constants
	def validateEmail = {email ->
		return email && emailPattern.matcher(email).matches()
	}
	
	//validate the email constants
	void testEmailConstants() {
		VALID_EMAILS.each {
			assertTrue validateEmail(it)
		}
		
		INVALID_EMAILS.each {
			assertFalse validateEmail(it)
		}
	}
	
	//Password constants
	static final def VALID_PASSWORDS = ['123456', '1234567', '12345678']
	static final def INVALID_PASSWORDS = [null, '', '12345', '123456789']
	static final Integer MIN_PASSWORD_SIZE = 6
	static final Integer MAX_PASSWORD_SIZE = 8
	
	//closure used to verify password constants
	def validatePassword = {password ->
		return password && MIN_PASSWORD_SIZE <= password?.length() &&
			MAX_PASSWORD_SIZE >= password?.length()
	}
	
	//validate the password constants
	void testPasswordConstants() {
		VALID_PASSWORDS.each {
			assertTrue(validatePassword(it))
		}
		
		INVALID_PASSWORDS.each {
			assertFalse validatePassword(it)
		}
	}
	
	//C-1: Customers have email address, password and created date fields
	void testCustomerFields() {
		def customer = new Customer(email : VALID_EMAILS[0], password : VALID_PASSWORDS[0])
		customer.save(flush : true)
		assertNotNull customer.email
		assertNotNull customer.password
		assertNotNull customer.dateCreated
	}
	
	//Email failures are for null, blank, or invalid email format
	def invalidEmailCausesValidationError = {
		return 'nullable' == it || 'blank' == it || 'email.invalid' == it
	}
	
	//C-3: Email address must be of a valid form (@.*) (unit test)
	void testInvalidEmailFormatsFailValidation() {
		INVALID_EMAILS.each {
			def customer = new Customer(email : it)
			customer.validate()
			assertTrue (invalidEmailCausesValidationError(customer.errors['email'].code))
		}
	}

	//C-3: Email address must be of a valid form (@.*) (unit test)
	void testValidEmailFormatsDoesNotFailValidation() {
		def customer = new Customer(email : VALID_EMAILS[0])
		customer.validate()
		assertNull customer.errors['email']
	}

	//Password failures are caused by a null field, blank,  or size failures
	def invalidPasswordCausesValidationError = {
		return 'nullable' == it || 'blank' == it || 'size.toosmall' == it || 'size.toobig' == it
	}
	//C-4: Password must be between 6-8 characters (unit test)
	void testInvalidPasswordsFailValidation() {
		INVALID_PASSWORDS.each {
			def customer = new Customer(password : it)
			customer.validate()
			assertTrue(invalidPasswordCausesValidationError(customer.errors['password'].code))
		}
	}

	//C-4: Password must be between 6-8 characters (unit test)
	void testValidPasswordsDoesNotFailValidation() {
		VALID_PASSWORDS.each {
			def customer = new Customer(password : it)
			customer.validate()
			assertNull customer.errors['password']
		}
	}
}
